﻿namespace ScrumLite.WebUx.Tests
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using ScrumLite.Services;
    using ScrumLite.Services.Contracts;

    public class MockCommitmentsService : ICommitmentsService
    {
        public const string ProjectIdForEmptyData = "13c659fb-fa13-4343-ba36-1af8b48eee97";
        public static DateTime fechaBase = new DateTime(2008, 02, 15);
        public bool AddCommitmentCalled { get; set; }
        public bool DeleteCommitmentCalled { get; set; }
        public bool GetWeeklyCommitmentsCalled { get; set; }
        public Commitment CommitmentAdded { get; set; }
        public static List<DateTime> DatesToReturn { get; private set; }
        public static Dictionary<DateTime, List<Commitment>> CommitmentsToReturn { get; private set; }

        public MockCommitmentsService()
        {
            InitializeData();
        }

        private static void InitializeData()
        {
            DatesToReturn = new List<DateTime>(new DateTime[] {
                        fechaBase,
                        fechaBase.Subtract(TimeSpan.FromDays(1)).Date,
                        fechaBase.Subtract(TimeSpan.FromDays(2)).Date,
                        fechaBase.Subtract(TimeSpan.FromDays(3)).Date,
                        fechaBase.Subtract(TimeSpan.FromDays(4)).Date                      });

            CommitmentsToReturn = new Dictionary<DateTime, List<Commitment>>();
            CommitmentsToReturn.Add(DatesToReturn[0], new List<Commitment>(new Commitment[] {
                    new Commitment() { Title = "Create Commitments/Request DB", CreatedBy = "Maximiliano Amoretti", CreatedOn = DatesToReturn[0], Verification = "DB created", Left = 0, Spent = 3 },
                    new Commitment() { Title = "Build Commitments CRUD page", CreatedBy = "Marcelo Rodriguez", CreatedOn = DatesToReturn[0], Verification = "Commitments page and mock services running", Left = 0, Spent = 5 },
                    new Commitment() { Title = "Solve Windows Authentication issue", CreatedBy = "Matias Woloski", CreatedOn = DatesToReturn[0], Verification = "Authentication issue fixed", Left = 4, Spent = 2 },
                    new Commitment() { Title = "Create tests for controller", CreatedBy = "John Foo", CreatedOn = DatesToReturn[0], Verification = "Tests for controller checked in", Left = 2, Spent = 1 }
                }));
            CommitmentsToReturn.Add(DatesToReturn[1], new List<Commitment>(new Commitment[] {
                    new Commitment() { Title = "Commitment 3", CreatedBy = "Maximiliano Amoretti", CreatedOn = DatesToReturn[1], Verification = "verification 3", Left = 0 },
                    new Commitment() { Title = "Commitment 1", CreatedBy = "Marcelo Rodriguez", CreatedOn = DatesToReturn[1], Verification = "verification 1", Left = 0 },
                    new Commitment() { Title = "Commitment 2", CreatedBy = "Matias Woloski", CreatedOn = DatesToReturn[1], Verification = "verification 2", Left = 0 },
                    new Commitment() { Title = "Commitment 4", CreatedBy = "Marcelo Rodriguez", CreatedOn = DatesToReturn[1], Verification = "verification 4", Left = 2 }
                }));
            CommitmentsToReturn.Add(DatesToReturn[2], new List<Commitment>(new Commitment[] {
                    new Commitment() { Title = "Commitment C", CreatedBy = "Maximiliano Amoretti", CreatedOn = DatesToReturn[2], Verification = "verification C", Left = 0 },
                    new Commitment() { Title = "Commitment A", CreatedBy = "Marcelo Rodriguez", CreatedOn = DatesToReturn[2], Verification = "verification A", Left = 0 },
                    new Commitment() { Title = "Commitment B", CreatedBy = "Matias Woloski", CreatedOn = DatesToReturn[2], Verification = "verification B", Left = 0 }
                }));
            CommitmentsToReturn.Add(DatesToReturn[3], new List<Commitment>(new Commitment[] {
                    new Commitment() { Title = "Commitment III", CreatedBy = "Maximiliano Amoretti", CreatedOn = DatesToReturn[3], Verification = "verification III", Left = 0 },
                    new Commitment() { Title = "Commitment I", CreatedBy = "Marcelo Rodriguez", CreatedOn = DatesToReturn[3], Verification = "verification I", Left = 0 },
                    new Commitment() { Title = "Commitment II", CreatedBy = "Matias Woloski", CreatedOn = DatesToReturn[3], Verification = "verification II", Left = 0 }
                }));
            CommitmentsToReturn.Add(DatesToReturn[4], new List<Commitment>(new Commitment[] {
                    new Commitment() { Title = "Commitment c", CreatedBy = "Maximiliano Amoretti", CreatedOn = DatesToReturn[4], Verification = "verification c" },
                    new Commitment() { Title = "Commitment a", CreatedBy = "Marcelo Rodriguez", CreatedOn = DatesToReturn[4], Verification = "verification a" },
                    new Commitment() { Title = "Commitment b", CreatedBy = "Matias Woloski", CreatedOn = DatesToReturn[4], Verification = "verification b" }
                }));
        }

        public DateTime[] GetStandupDates(string projectId)
        {
            return DatesToReturn.ToArray();
        }

        public Commitment[] GetCommitments(DateTime commitmentDate, string projectId)
        {
            return CommitmentsToReturn.ContainsKey(commitmentDate) ? CommitmentsToReturn[commitmentDate].ToArray() : null;
        }

        public void Add(string projectId, Commitment commitment)
        {
            AddCommitmentCalled = true;
            CommitmentAdded = commitment;
            if (CommitmentsToReturn.ContainsKey(commitment.CreatedOn))
            {
                List<Commitment> list = CommitmentsToReturn[commitment.CreatedOn];
                list.Add(commitment);
                CommitmentsToReturn[commitment.CreatedOn] = list;
            }
            else
            {
                CommitmentsToReturn[commitment.CreatedOn] = new List<Commitment>() { commitment };
            }
        }

        public void Delete(Guid id)
        {
            DeleteCommitmentCalled = true;
        }

        public void Update(Commitment commitment)
        {
            throw new NotImplementedException();
        }

        public Commitment GetCommitment(Guid commitmentId)
        {
            throw new NotImplementedException();
        }

        public Dictionary<int, int> GetWeeklyCommitmentsCount(string projectId, bool closed)
        {
            GetWeeklyCommitmentsCalled = true;
                Dictionary<int, int> result = new Dictionary<int, int>();

                if (projectId == "AF06A611-12CE-4C06-B3AD-E2754D12D516")
                {
                    foreach (KeyValuePair<DateTime, List<Commitment>> kp in CommitmentsToReturn)
                    {
                        foreach (Commitment comm in kp.Value)
                        {
                            if ((comm.Left == 0) == closed)
                            {
                                int weekNumber = GetCommitmentWeek(comm.CreatedOn);
                                if (!result.ContainsKey(weekNumber))
                                {
                                    result.Add(weekNumber, 1);
                                }
                                else
                                {
                                    result[weekNumber]++;
                                }
                            }
                        }
                    }
                }
            return result;
        }

        private static int GetCommitmentWeek(DateTime date)
        {
            CultureInfo invariant=CultureInfo.InvariantCulture;
            return invariant.Calendar.GetWeekOfYear(date,
                                   invariant.DateTimeFormat.CalendarWeekRule,
                                   invariant.DateTimeFormat.FirstDayOfWeek);
        }
    }
}
